#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

import pygame
from lib import Pan
from pygame.locals import *

try:
    import psyco
    psyco.full()
except:
    print "install psyco for better performace!"

game_name = "civilization"
game = __import__( game_name )

BG_COLOR = ( 0, 0, 0 )
WIDTH = 800
HEIGHT = 600
FLAGS = DOUBLEBUF | RESIZABLE
""" ""
WIDTH = 1680
HEIGHT = 1050
FLAGS = FULLSCREEN | HWSURFACE
"" """
PAN_SPEED = 10
ZOOM_SPEED = 0.1
MAX_ZOOM = 1.5
MIN_ZOOM = round( min( (1.0 * WIDTH) / game.width, (1.0 * HEIGHT) / game.height ) - 0.005, 2 )
MIN_ZOOM = 0.1
X = 0
Y = 1

import cProfile

# fallback scaling
if not hasattr( pygame.transform, "smoothscale" ):
    print "install pygame 1.8 for better scaling!"
    pygame.transform.smoothscale = pygame.transform.scale

"""
Grazie a ocemp per l'idea!

##################   ###
#                #   # # GameArea
#  *********     #   ###
#  *       *     #
#  *********     #   ***
#                #   * * Screen
#                #   ***
##################

La GameArea contiene tutti gli elementi e non cambia mai dimensione e posizione
Lo Screen puo' cambiare posizione (pan) e dimensione (zoom) nel tempo
Lo Screen copia (blit) una porzione della GameArea trasformando (zoom) il contenuto

dovrebbe funzionare..
"""

def foo():
    pygame.init()
    flipper = 2

    screen = pygame.display.set_mode( ( WIDTH, HEIGHT ), FLAGS )

    pygame.display.set_caption( "e-Board :: Board Gameing Evolved" )

    class GameArea( pygame.Surface ):
        def __init__( self, size ):
            pygame.Surface.__init__( self, size )
            self.width = size[X]
            self.height = size[Y]
            self.pan_x = 0
            self.pan_y = 0
            self.zoom = 0.5
            self.scaled = None

        def scale( self ):
            if self.zoom == 1:
                self.scaled = self
            else:
                w = int( self.width * self.zoom )
                h = int( self.height * self.zoom )
                # smoothscale output is much better but slower than scale
                self.scaled = pygame.transform.smoothscale( self, ( w, h ) )

        def set_zoom( self, zoom ):
            zoom = max( zoom, MIN_ZOOM )
            zoom = min( zoom, MAX_ZOOM )
            if zoom != self.zoom:
                self.scaled = None
                self.pan_x += 10
                self.pan_y += 10
            self.zoom = zoom

        def set_pan( self, pan ):
            self.pan_x = pan[X]
            self.pan_y = pan[Y]

        def draw( self, screen ):
            if not self.scaled:
                self.scale()
            screen.blit( self.scaled, ( self.pan_x, self.pan_y ) )

    gamearea = GameArea( ( game.width, game.height ) )
    #gamearea.fill( game.bg_color )

    sprites = pygame.sprite.RenderUpdates()
    for element in game.materials:
        sprites.add( element )

    def clear_callback( surf, rect ):
        pass #surf.fill( game.bg_color, rect )

    def get_sprite_at_pos( position ):
        x = position[0]
        y = position[1]
        retval = None
        for sprite in sprites:
            if sprite.rect.x < x and \
                sprite.rect.y < y and \
                ( sprite.rect.x + sprite.rect.width ) > x and \
                ( sprite.rect.y + sprite.rect.height ) > y:
                if not retval or retval.zindex < sprite.zindex:
                    retval = sprite
        return retval

    clock = pygame.time.Clock()

    running = True

    gesture = False

    panning = [ 0, 0 ]
    pan_x = 0
    pan_y = 0

    zoom = 0.5
    redraw = True
    oldw = 0
    oldh = 0

    margin = 20

    while running:
        # handle events
        for event in pygame.event.get():
            if event.type == NOEVENT:
                continue

            elif event.type == QUIT or \
                ( event.type == KEYDOWN and event.key == K_ESCAPE ):
                running = False

            elif event.type == MOUSEBUTTONDOWN:
                if not gesture:
                    #gesture = Gesture( pygame.mouse.get_pos() )
                    gesture = Pan( pygame.mouse.get_pos(), ( pan_x, pan_y ), pygame.display.get_surface().get_size(), zoom )
                if event.button == 4: # wheel up
                    print "Wheel UP"
                if event.button == 5: # wheel down
                    print "Wheel DOWN"

            elif event.type == MOUSEMOTION:
                if gesture:
                    pos = pygame.mouse.get_pos()
                    gesture.add_point( pos )
                    redraw = True

            elif event.type == MOUSEBUTTONUP:
                if gesture:
                    gesture.resolve()
                    gesture = False
                    redraw = True

            elif event.type == VIDEORESIZE:
                screen = pygame.display.set_mode( event.size, FLAGS )
                redraw = True

            elif event.type == KEYDOWN:
                pass

            elif event.type == KEYUP:
                if event.key == K_c:
                    zoom = 1
                    redraw = True

        if gesture:
            pan_x, pan_y = gesture.get_panxy()
            zoom = gesture.get_zoom( MIN_ZOOM, MAX_ZOOM )

            if zoom < MIN_ZOOM:
                zoom = MIN_ZOOM

            if zoom > MAX_ZOOM:
                zoom = MAX_ZOOM

            area = pygame.display.get_surface().get_size()
            """
            if pan_x > max( 0, area[ X ]-int( game.width * zoom )):
                pan_x = max( 0, area[ X ]-int( game.width * zoom ))

            if pan_y > max(0, area[ Y ]-int( game.height * zoom )):
                pan_y = max(0, area[ Y ]-int( game.height * zoom ))

            if pan_x < min( 0, area[ X ]-int( game.width * zoom )):
                pan_x = min( 0, area[ X ]-int( game.width * zoom ))

            if pan_y < min(0, area[ Y ]-int( game.height * zoom )):
                pan_y = min(0, area[ Y ]-int( game.height * zoom ))
            """
        if redraw:
            flipper = 2
            redraw = False

            area = pygame.display.get_surface().get_size()
            w = int( game.width * zoom )
            h = int( game.height * zoom )

            if w < area[ X ] or h < area[ Y ]:
                screen.fill( BG_COLOR )

            # aggiorna la gamearea
            sprites.clear( gamearea, clear_callback )
            sprites.draw( gamearea )

            # applica lo spostamento dall'angolo alto sinistro
            gamearea.set_pan( ( pan_x, pan_y ) )
            gamearea.set_zoom( zoom )
            gamearea.draw( screen )

            # disegna il limite zoom/pan
            area = pygame.display.get_surface().get_size()
            pygame.draw.aalines( screen, (32,32,32), True, [ (margin, margin), (area[0]-margin, margin), (area[0]-margin,area[1]-margin), (margin, area[1]-margin) ])
            #for w in range(20,area[ X ], 20):
            #    pygame.draw.aaline( screen, (255,255,255), (20,w),(w,20) )


            pygame.draw.aaline( screen, (255,255,255), (area[ X ]/2, 0), (area[ X ]/2, area[ Y ]), 1 )
            pygame.draw.aaline( screen, (255,255,255), (0, area[ Y ]/2), (area[ X ], area[ Y ]/2), 1 )

        if gesture:
            flipper = 2
            gesture.draw( screen )

        if flipper > 0 :
            flipper -= 1
            pygame.display.flip()

        clock.tick( 50 )

cProfile.run('foo()')

